<html lang="zh-CN"><head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>用户购买意向与推荐系统</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.8/dist/chart.umd.min.js"></script>
</head>
<body class="bg-gray-50">
    <!-- 导航栏 -->
    <nav class="bg-blue-600 text-white shadow-md">
        <div class="container mx-auto px-4 py-3 flex justify-between items-center">
            <h1 class="text-xl font-bold">电商数据分析平台</h1>
            <div class="space-x-4">
                <a href="/" class="hover:text-blue-200"><i class="fa fa-home mr-1"></i>首页</a>
                <a href="/prediction_monitoring" class="hover:text-blue-200"><i class="fa fa-line-chart mr-1"></i>购买预测</a>
                <a href="/rfm_segmentation" class="hover:text-blue-200"><i class="fa fa-users mr-1"></i>RFM分析</a>
            </div>
        </div>
    </nav>

    <!-- 购买意向预测页面 -->
    <div id="prediction-monitoring" class="container mx-auto px-4 py-8">
        <h2 class="text-2xl font-bold mb-6 text-gray-800">用户购买意向预测</h2>

        <!-- 模型性能指标 -->
        <div class="bg-white rounded-lg shadow-md p-6 mb-8">
            <h3 class="text-xl font-semibold mb-4 text-gray-700">模型性能</h3>
            <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
                <div>
                    <h4 class="text-lg font-medium text-gray-600 mb-2">AUC 得分</h4>
                    <div class="flex items-center">
                        <div class="w-full bg-gray-200 rounded-full h-4">
                            <div id="auc-progress" class="bg-green-500 h-4 rounded-full" style="width: 0%"></div>
                        </div>
                        <span id="auc-score" class="ml-4 text-lg font-bold">--</span>
                    </div>
                </div>
                <div>
                    <h4 class="text-lg font-medium text-gray-600 mb-2">训练样本量</h4>
                    <p id="sample-size" class="text-xl font-mono">--</p>
                </div>
                <div>
                    <h4 class="text-lg font-medium text-gray-600 mb-2">模型训练时间</h4>
                    <p id="training-time" class="text-xl font-mono">--</p>
                </div>
            </div>
        </div>

        <!-- 购买概率分布 -->
        <div class="bg-white rounded-lg shadow-md p-6 mb-8">
            <h3 class="text-xl font-semibold mb-4 text-gray-700">购买概率分布</h3>
            <div class="h-80">
                <canvas id="probability-chart"></canvas>
            </div>
        </div>

        <!-- 用户推荐查询 -->
        <div class="bg-white rounded-lg shadow-md p-6 mb-8">
            <h3 class="text-xl font-semibold mb-4 text-gray-700">个性化推荐</h3>
            <div class="flex flex-col md:flex-row gap-4">
                <div class="flex-grow">
                    <label for="user-id" class="block text-gray-700 mb-2">用户ID</label>
                    <input type="number" id="user-id" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="输入用户ID（例如：556696）">
                </div>
                <div class="flex-grow md:w-40">
                    <label for="rec-count" class="block text-gray-700 mb-2">推荐数量</label>
                    <input type="number" id="rec-count" value="10" min="1" max="50" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
                </div>
                <div class="flex items-end">
                    <button id="get-recommendations" class="bg-blue-600 text-white px-6 py-2 rounded-md hover:bg-blue-700 transition-colors">
                        <i class="fa fa-search mr-1"></i>获取推荐
                    </button>
                </div>
            </div>

            <!-- 推荐结果 -->
            <div id="recommendations-result" class="mt-6 hidden">
                <h4 class="text-lg font-medium text-gray-600 mb-3">为用户 <span id="current-user-id" class="font-bold"></span> 推荐的商品</h4>
                <div class="overflow-x-auto">
                    <table class="min-w-full bg-white">
                        <thead>
                            <tr class="bg-gray-100 text-gray-700">
                                <th class="py-3 px-4 text-left">商品ID</th>
                                <th class="py-3 px-4 text-left">购买概率</th>
                                <th class="py-3 px-4 text-left">推荐优先级</th>
                            </tr>
                        </thead>
                        <tbody id="recommendations-table-body">
                            <!-- 推荐结果将通过JS动态填充 -->
                        </tbody>
                    </table>
                </div>
            </div>
        </div>

        <!-- 顶部购买意向用户 -->
        <div class="bg-white rounded-lg shadow-md p-6">
            <div class="flex justify-between items-center mb-4">
                <h3 class="text-xl font-semibold text-gray-700">用户购买概率排行榜</h3>
                <button id="download-ranking" class="bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700 transition-colors">
                    <i class="fa fa-download mr-1"></i>下载PDF
                </button>
            </div>
            <div class="overflow-x-auto">
                <table class="min-w-full bg-white">
                    <thead>
                        <tr class="bg-gray-100 text-gray-700">
                            <th class="py-3 px-4 text-left">排名</th>
                            <th class="py-3 px-4 text-left">用户ID</th>
                            <th class="py-3 px-4 text-left">推荐商品ID</th>
                            <th class="py-3 px-4 text-left">购买概率</th>
                        </tr>
                    </thead>
                    <tbody id="top-users-table-body">
                        <!-- 高意向用户数据将通过JS动态填充 -->
                    </tbody>
                </table>
            </div>
        </div>
    </div>

    <script>
        // 页面加载时获取购买意向数据
        document.addEventListener('DOMContentLoaded', function() {
            // 显示加载状态
            showLoadingState();

            // 获取购买意向排名数据
            fetch('/api/purchase_intention')
                .then(response => {
                    if (!response.ok) {
                        throw new Error(`HTTP error! Status: ${response.status}`);
                    }
                    return response.json();
                })
                .then(data => {
                    hideLoadingState();
                    renderTopUsersTable(data);
                    renderProbabilityDistribution(data);
                    calculateModelMetrics(data);
                })
                .catch(error => {
                    hideLoadingState();
                    console.error('获取购买意向数据失败:', error);
                    showErrorMsg('获取数据失败，请刷新页面重试');
                });

            // 绑定推荐查询按钮事件
            document.getElementById('get-recommendations').addEventListener('click', function() {
                const userId = document.getElementById('user-id').value;
                const recCount = document.getElementById('rec-count').value;

                if (!userId) {
                    alert('请输入用户ID');
                    return;
                }

                showLoadingState();

                fetch(`/api/recommendations?user_id=${userId}&num_recs=${recCount}`)
                    .then(response => {
                        if (!response.ok) {
                            throw new Error(`HTTP error! Status: ${response.status}`);
                        }
                        return response.json();
                    })
                    .then(recs => {
                        hideLoadingState();
                        renderRecommendations(userId, recs);
                    })
                    .catch(error => {
                        hideLoadingState();
                        console.error('获取推荐数据失败:', error);
                        showErrorMsg('获取推荐失败，请重试');
                    });
            });

            // 绑定下载按钮事件
            document.getElementById('download-ranking').addEventListener('click', function() {
                showLoadingState();
                // 调用下载API
                fetch('/api/download_purchase_ranking')
                    .then(response => {
                        hideLoadingState();
                        if (!response.ok) {
                            throw new Error(`下载失败: ${response.status}`);
                        }
                        return response.blob();
                    })
                    .then(blob => {
                        // 创建下载链接
                        const url = window.URL.createObjectURL(blob);
                        const a = document.createElement('a');
                        a.href = url;
                        a.download = 'purchase_probability_ranking.pdf';
                        document.body.appendChild(a);
                        a.click();
                        window.URL.revokeObjectURL(url);
                        document.body.removeChild(a);
                    })
                    .catch(error => {
                        hideLoadingState();
                        console.error('下载失败:', error);
                        showErrorMsg('下载失败，请重试');
                    });
            });
        });

        // 显示加载状态
        function showLoadingState() {
            // 创建加载指示器（如果不存在）
            if (!document.getElementById('loading-indicator')) {
                const loader = document.createElement('div');
                loader.id = 'loading-indicator';
                loader.className = 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50';
                loader.innerHTML = `
                    <div class="bg-white p-6 rounded-lg shadow-lg">
                        <div class="flex items-center">
                            <i class="fa fa-circle-o-notch fa-spin text-blue-600 text-2xl mr-3"></i>
                            <p class="text-gray-700">数据加载中...</p>
                        </div>
                    </div>
                `;
                document.body.appendChild(loader);
            }
        }

        // 隐藏加载状态
        function hideLoadingState() {
            const loader = document.getElementById('loading-indicator');
            if (loader) {
                document.body.removeChild(loader);
            }
        }

        // 显示错误消息
        function showErrorMsg(message) {
            alert(message);
        }

        // 渲染高购买意向用户表格
        function renderTopUsersTable(data) {
            const tableBody = document.getElementById('top-users-table-body');
            tableBody.innerHTML = '';

            // 检查数据是否有效
            if (!data || data.length === 0) {
                const row = document.createElement('tr');
                row.innerHTML = `<td colspan="4" class="py-3 px-4 text-center text-gray-500">没有找到高购买意向用户数据</td>`;
                tableBody.appendChild(row);
                return;
            }

            // 获取去重后的前10位用户
            const uniqueUsers = [...new Map(data.map(item => [item.user_id, item])).values()].slice(0, 10);

            uniqueUsers.forEach((user, index) => {
                const row = document.createElement('tr');
                row.className = index % 2 === 0 ? 'bg-white' : 'bg-gray-50';
                // 格式化购买概率显示，根据日志中的数据格式调整
                const probability = user.购买概率 ? (user.购买概率 * 100).toFixed(4) : '0.0000';
                row.innerHTML = `
                    <td class="py-3 px-4">${index + 1}</td>
                    <td class="py-3 px-4">${user.user_id}</td>
                    <td class="py-3 px-4">${user.item_id}</td>
                    <td class="py-3 px-4">${probability}%</td>
                `;
                tableBody.appendChild(row);
            });
        }

        // 渲染购买概率分布图表
        function renderProbabilityDistribution(data) {
            const ctx = document.getElementById('probability-chart').getContext('2d');

            // 提取概率数据并分组
            const probabilities = data.map(item => item.购买概率 || 0);
            const bins = [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0];
            const counts = new Array(bins.length - 1).fill(0);

            probabilities.forEach(prob => {
                for (let i = 0; i < bins.length - 1; i++) {
                    if (prob >= bins[i] && prob < bins[i + 1]) {
                        counts[i]++;
                        break;
                    }
                }
            });

            // 销毁已存在的图表
            if (window.probabilityChart) {
                window.probabilityChart.destroy();
            }

            window.probabilityChart = new Chart(ctx, {
                type: 'bar',
                data: {
                    labels: bins.slice(0, -1).map((bin, i) => `${bin.toFixed(1)}-${bins[i+1].toFixed(1)}`),
                    datasets: [{
                        label: '用户-商品对数量',
                        data: counts,
                        backgroundColor: 'rgba(54, 162, 235, 0.7)',
                        borderColor: 'rgba(54, 162, 235, 1)',
                        borderWidth: 1
                    }]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    scales: {
                        y: {
                            beginAtZero: true,
                            title: {
                                display: true,
                                text: '数量'
                            }
                        },
                        x: {
                            title: {
                                display: true,
                                text: '购买概率区间'
                            }
                        }
                    },
                    plugins: {
                        title: {
                            display: true,
                            text: '用户购买概率分布'
                        },
                        tooltip: {
                            callbacks: {
                                label: function(context) {
                                    return `数量: ${context.raw}`;
                                }
                            }
                        }
                    }
                }
            });
        }

        // 计算并显示模型指标
        function calculateModelMetrics(data) {
            // 从数据中提取AUC值（实际应用中应从专门的API获取）
            // 根据日志中的信息，AUC值为0.9976
            const aucScore = 0.9976;
            document.getElementById('auc-score').textContent = aucScore.toFixed(4);
            document.getElementById('auc-progress').style.width = `${Math.min(aucScore * 100, 100)}%`;

            // 显示样本量（根据日志，样本量为2504）
            document.getElementById('sample-size').textContent = '2,504';

            // 显示模型训练时间（根据日志，约为0.16秒）
            document.getElementById('training-time').textContent = '0.16秒';
        }

        // 渲染用户推荐结果
        function renderRecommendations(userId, recommendations) {
            const resultContainer = document.getElementById('recommendations-result');
            const tableBody = document.getElementById('recommendations-table-body');
            const currentUserId = document.getElementById('current-user-id');

            currentUserId.textContent = userId;
            tableBody.innerHTML = '';

            // 处理空推荐结果（如日志中用户556696的情况）
            if (!recommendations || recommendations.length === 0) {
                const row = document.createElement('tr');
                row.innerHTML = `<td colspan="3" class="py-3 px-4 text-center text-gray-500">没有找到该用户的推荐数据</td>`;
                tableBody.appendChild(row);
            } else {
                recommendations.forEach((rec, index) => {
                    const row = document.createElement('tr');
                    row.className = index % 2 === 0 ? 'bg-white' : 'bg-gray-50';
                    const probability = rec.购买概率 ? (rec.购买概率 * 100).toFixed(4) : '0.0000';
                    row.innerHTML = `
                        <td class="py-3 px-4">${rec.item_id}</td>
                        <td class="py-3 px-4">${probability}%</td>
                        <td class="py-3 px-4">${index + 1}</td>
                    `;
                    tableBody.appendChild(row);
                });
            }

            resultContainer.classList.remove('hidden');
        }
    </script>


</body></html>